package com.powernode.proxy.service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 专门负责计时的一个调用处理器对象
// 这个调用处理器当中编写计时相关的增强代码
// 这个调用处理器只需要写一个就行了
public class TimerInvocationHandler implements InvocationHandler {
    // 目标对象
    private Object target;

    public TimerInvocationHandler(Object target) {
        this.target = target;
    }

    /*
        1.为什么强行要求你实现InvocationHandler接口
            因为一个类实现接口必须要实现接口中的方法
            以下这个方法必须是invoke(),因为JDK在底层会调用invoke()方法已经提前写好了
            注意：invoke方法不是我们程序员调用的，是JDK负责调用的

         2.invoke方法什么时候调用呢？
            当代理对象调用代理方法时，注册在InvocationHandler调用处理器当中的invoke()方法被调用

        3.invoke()方法三个参数
            invoke方法是JDK负责调用的，所有JDK调用这个方法的时候会自动给我们传过来这三个参数
            我们可以在invoke方法中直接使用
            第一个参数：Object proxy
                代理对象的引用，这个参数使用较少
            第二个参数：Method method
                目标对象上的目标方法（要执行的目标方法就是他）
            第三个参数：Object[] args
                目标方法上的实参

        4.invoke()方法的返回值
            目标方法的返回值
         */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 这个接口的目的是为了让你有地方写增强代码
        long begin=System.currentTimeMillis();
        // 调用目标对象上的目标方法
        // 方法四要素：哪个对象 哪个方法 传什么参数 返回什么值
        Object retValue = method.invoke(target, args);
        long end=System.currentTimeMillis();
        System.out.println("耗时："+(end-begin)+"毫秒");
        // 注意：如果代理对象调用代理方法之后，需要目标对象的目标方法返回结果的话，invoke方法必须将目标对象的目标方法继续返回
        return retValue;
    }
}
